package com.zzyy.study.interceptor;

import com.zzyy.study.annotations.IdempotentAnnotation;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/** 创建拦截器
 * @auther zzyy
 * @create 2024-12-28 16:26
 */
@Component
public class IdempotentInterceptor implements HandlerInterceptor
{
    public static final String REDIS_KEY_PREFIX = "idempotent:";

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 前置处理逻辑
        System.out.println("IdempotentInterceptor拦截器 前置处理逻辑preHandle getRequestURI: " + request.getRequestURI());

        Method method = ((HandlerMethod) handler).getMethod();
        IdempotentAnnotation idempotentAnnotation = method.getAnnotation(IdempotentAnnotation.class);

        if (idempotentAnnotation != null) {
            // 获取请求中的唯一标识符
            String requestId = request.getParameter(idempotentAnnotation.requestId());
            // 判断该请求是否已经处理过
            if (redisTemplate.opsForValue().get(REDIS_KEY_PREFIX + requestId) != null)
            {
                response.setContentType("text/html;charset=UTF-8");
                response.setCharacterEncoding("UTF-8");
                // 已经处理过，返回幂等响应
                response.getWriter().write("重复请求发生，幂等判断触发");
                return false;
            } else {
                // 将请求标识符存入Redis，并设置过期时间
                redisTemplate.opsForValue().set(REDIS_KEY_PREFIX + requestId, "processed", idempotentAnnotation.expireTime(), TimeUnit.SECONDS);
                return true; // 继续执行业务逻辑
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 后置处理逻辑（可选）
        // 注意：如果preHandle返回false，则不会调用此方法
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 资源清理或其他后续处理逻辑（可选）
        // 注意：此方法总是在请求处理完成后被调用，无论是否发生异常

        System.out.println("IdempotentInterceptor拦截器 后置处理逻辑afterCompletion method");
    }

}
